package com.spark.gaea.data.mybatis;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.spark.gaea.base.Page;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.io.Serializable;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

@Repository
public class Dao extends SqlSessionDaoSupport {
	@Override
	@Autowired
	public void setSqlSessionFactory(final SqlSessionFactory sqlSessionFactory) {
		super.setSqlSessionFactory(sqlSessionFactory);
	}

	public void insert(final String prefix, final String key, final Object object) {
		this.getSqlSession().insert(prefix + key, object);
	}

	public void update(final String prefix, final String key, final Object object) {
		this.getSqlSession().update(prefix + key, object);
	}

	public void delete(final String prefix, final String key, final Serializable id) {
		this.getSqlSession().delete(prefix + key, id);
	}

	public void delete(final String key, final Serializable id) {
		this.getSqlSession().delete(key, id);
	}

	public void delete(final String prefix, final String key, final Object object) {
		this.getSqlSession().delete(prefix + key, object);
	}

	public <T> T get(final String prefix, final String key, final Object params) {
		return (T) this.getSqlSession().selectOne(prefix + key, params);
	}

	public <T> List<T> getList(final String prefix, final String key) {
		return (List<T>) this.getSqlSession().selectList(prefix + key);
	}

	public <T> List<T> getList(final String prefix, final String key, final Object params) {
		return (List<T>) this.getSqlSession().selectList(prefix + key, params);
	}

	public Integer count(final String prefix, final String key, final Object params) {
		return (Integer) this.getSqlSession().selectOne(prefix + key, params);
	}

	public Object[] page(final String prefix, final String pageKey, final String countKey, final Object params,
			final int offset, final int limit) {
		return new Object[]{this.getSqlSession().selectList(prefix + pageKey, params, new RowBounds(offset, limit)),
				this.getSqlSession().selectOne(prefix + countKey, params)};
	}

	public Page page(final String prefix, final String pageKey, final String countKey, final Object params,
			final Page pager) {
		pager.setList(this.getSqlSession()
						.selectList(prefix + pageKey, params, new RowBounds(pager.getStartIndex(), pager.getPagesize())),
				(Integer) this.getSqlSession().selectOne(prefix + countKey, params));
		return pager;
	}

	public boolean executeSql(final String sql) {
		try {
			return this.getSqlSession().getConnection().prepareStatement(sql).execute();
		} catch (SQLException e) {
			e.printStackTrace();
			return false;
		}
	}

	public List<Map> querySql(final String sql) {
		final List<Map> list = Lists.newArrayList();
		try {
			final ResultSet rs = this.getSqlSession().getConnection().prepareStatement(sql, 1004, 1008).executeQuery();
			try {
				final ResultSetMetaData rsm = rs.getMetaData();
				final int col = rsm.getColumnCount();
				final String[] colName = new String[col];
				for (int i = 0; i < col; ++i) {
					colName[i] = rsm.getColumnName(i + 1);
				}
				rs.beforeFirst();
				while (rs.next()) {
					final Map<String, String> map = Maps.newHashMap();
					for (final String aColName : colName) {
						map.put(aColName, rs.getString(aColName));
					}
					list.add(map);
				}
			} catch (SQLException e) {
				e.printStackTrace();
				return null;
			}
		} catch (SQLException e2) {
			e2.printStackTrace();
		}
		return list;
	}
}
